#include "../include/logBase.h"


logEnum& logEnum::Init()
{
	static logEnum le;
	return le;
}

logMsg::logMsg()
{
	clear();
}

logMsg::logMsg(const std::string& data, int level, const std::string& loggerName, const std::string& fileName, size_t line)
{
	insert(data, level, loggerName, fileName, line);
}

void logMsg::clear()
{
	_time = 0;
	_id = std::thread::id();
	_line = 0;
	_level = 0;
	_fileName.clear();
	_data.clear();
	_loggerName.clear();
}

void logMsg::insert(const std::string& data, int level, const std::string& loggerName, const std::string& fileName, size_t line)
{
	_data = data;
	_level = level;
	_loggerName = loggerName;
	_fileName = fileName;
	_line = line;
	_id = std::this_thread::get_id();
	_time = Tool::nowTime();
}

void logFormat::insert(const std::string& key, const std::function<std::string(logMsg)>& fun)
{
	_formatFunMap.insert({ key, fun });
}

void logFormat::clear()
{
	_formatFunMap.clear();
}

std::function<std::string(logMsg)> logFormat::get(const std::string& key)
{
	if (_formatFunMap.count(key) == 1)
	{
		return _formatFunMap[key];
	}

	return std::function<std::string(logMsg)>();
}

Reformat::Reformat(const std::string& pattern)
{
	std::string temp;
	int i = 0;
	while (i < pattern.size())
	{
		if (pattern[i] == '%')
		{
			_pattern.push_back(temp);
			temp.clear();

			temp += pattern[i];
			temp += pattern[i + 1];
			_pattern.push_back(temp);
			temp.clear();
			i += 2;
		}
		else
		{
			temp += pattern[i];
			i++;
		}
	}
	if (!temp.empty())
	{
		_pattern.push_back(temp);
	}
}

void Reformat::setPattern(const std::string& logFormat)
{
	std::vector<std::string> pattern;
	std::string temp;
	int i = 0;
	while (i < logFormat.size())
	{
		if (logFormat[i] == '%')
		{
			pattern.push_back(temp);
			temp.clear();

			temp += logFormat[i];
			temp += logFormat[i + 1];
			pattern.push_back(temp);
			temp.clear();
			i += 2;
		}
		else
		{
			temp += logFormat[i];
			i++;
		}
	}
	if (!temp.empty())
	{
		pattern.push_back(temp);
	}
	_pattern.swap(pattern);
}

void Reformat::change(const std::string& key, const std::function<std::string(logMsg)>& fun)
{
	_logFormat.insert(key, fun);
}

void Reformat::clear()
{
	_logFormat.clear();
}

std::string Reformat::format(const logMsg& log)
{
	if (log._fileName.empty())
	{
		return "";
	}

	std::string ans;
	for (auto str : _pattern)
	{
		if (str[0] == '%')
		{
			auto fun = _logFormat.get(str);
			if (fun)
			{
				ans += fun(log);
			}	
		}
		else
		{
			ans += str;
		}
	}

	return ans;
}
